/**
 * Setvor project
 */
package setvor.npc;

import java.io.*;
import java.lang.reflect.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

/**
 * @author julatec
 *
 */
public class NativeException extends Exception implements NativeWriteable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 
	 */
	public NativeException() {
		super();
	}

	/**
	 * @param cause
	 */
	public NativeException(Throwable cause) {
		super(cause);
	}

	/**
	 * @param message
	 * @param cause
	 */
	public NativeException(String message, Throwable cause) {
		super(message, cause);
	}
	

	/**
	 * * This constructor get the stack form the serialized native
	 * message.
	 * @param nativeMessage
	 */
	public NativeException(String nativeMessage) {
		super(getMessage(nativeMessage), getStack(nativeMessage));
	}
	
	private static DocumentBuilderFactory factory;
	private static DocumentBuilder builder;

	static {
		try {
			factory = DocumentBuilderFactory.newInstance();
			builder = factory.newDocumentBuilder();
		}catch (Exception e) {
			e.printStackTrace(System.err);
			System.exit(0);
		}
	}
	
	private static String getMessage(String nativeMessage){
		//System.out.println("getting message");
		Document document;
		try {
			document = builder.parse(new java.io.ByteArrayInputStream(nativeMessage.getBytes()));
			//System.out.println(document.getDocumentElement());
			//System.out.println("nativeMessage"+nativeMessage+" Elements: "+document.getFirstChild().getFirstChild());
			return document.getFirstChild().getFirstChild().getTextContent();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private static Exception getStack(String nativeMessage){
		Document document;
		try {
			document = builder.parse(new java.io.ByteArrayInputStream(nativeMessage.getBytes()));
			//System.out.println(document.getDocumentElement());
			//System.out.println("nativeMessage"+nativeMessage+" Elements: "+document.getFirstChild().getFirstChild());
			NodeList lista = document.getFirstChild().getLastChild().getChildNodes();
			return getStack(lista, 0);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
		
	}
	
	@SuppressWarnings("unchecked")
	private static Exception getStack(NodeList lista, int index){
		if(lista.getLength()==index)
			return null;
		Element excepcion = (Element)lista.item(index);
		//System.out.println(excepcion.getTextContent());
		String clase = ((Element)excepcion).getFirstChild().getTextContent();
		String mensaje = ((Element)excepcion).getLastChild().getTextContent(); 
		index++;
		try {	
			Class clazz = Class.forName(clase);
			
			return  (Exception)(lista.getLength()==index ?
				clazz.getConstructor(String.class).newInstance(mensaje) :
				clazz.getConstructor(String.class, Exception.class).newInstance(mensaje,
						getStack(lista, index)));
		
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return null;
	}

}
